// 设计全局消息提示组件

// 1.由于是全局组件，要用一个公用的方法来调用显示消息组件。 onShow
// 2.由于是全局组件，方法也要挂到window上。 组件中调用方法：window.onShow()
// 3.消息提示组件弹出是最高层zindex。需要挂载到body中(手动创建div盒子，添加类名，添加到body)。
// 4.消息提示组件弹出后2s消失：需要设置一个定时器，定时器结束，消息提示组件消失。
// 5.怎么全局引入组件？在main.tsx 注入
// 6.在组件中调用window.onShow()测试效果
// 7.连续调用时，发现多个弹窗的位置重叠。需要做到antd的展示从上到下排列展示消息提示组件数组列表，并且要让当前显示的消息提示组件消失。
//   需要一个数组

import ReactDom, { createRoot } from 'react-dom/client'

import './index.css'

const Message = () => {
  return <div>消息提示</div>
}

// 7-3.定义列表类型
interface QueueItem {
  root: ReactDom.Root
  // 7-4.添加消息提示组件的容器类型，因为删除当前消息提示组件的时候，需要知道当前消息提示组件的容器。
  messageContainer: HTMLDivElement
}

// 7.消息提示组件数组列表
const queue: QueueItem[] = []

// 1、2.自定义一个全局触发方法 （代码写在最外层）。全局方法里面创建一个弹窗容器
window.onShow = () => {
  // 3.消息提示组件弹出是最高层zindex。需要挂载到body中。
  const messageContainer = document.createElement('div')
  messageContainer.className = 'message'
  // 7-2.从上到下展示消息提示列表。这种情况 是最新的消息提示在最下面。最终是从上到下删除
  // messageContainer.style.top = `${queue.length * 50}px`
  document.body.appendChild(messageContainer)
  // 3.容器做好了，如何将Message组件进行关联渲染？
  // 容器关联Message组件，如何关联？
  // 把容器注册成根组件--参考main.tsx
  const root = createRoot(messageContainer)
  root.render(<Message />)
  // 7-1.添加队列展示
  queue.push({
    root,
    messageContainer,
  })

  // 7-5. 优化：更新所有消息提示组件的top值，确保最新的在最上面。最终是从下往上消失效果
  queue.forEach((item, index) => {
    item.messageContainer.style.top = `${(queue.length - 1 - index) * 50}px`
  })
  setTimeout(() => {
    // // 7-4.删除当前消息提示组件
    // const currentMessage = queue.find((item) => item.messageContainer === messageContainer)!
    // // if (currentMessage) {  // 不用if判断的话，上面需要非空断言
    // currentMessage.root.unmount()
    // document.body.removeChild(currentMessage.messageContainer)
    // queue.splice(queue.indexOf(currentMessage), 1)
    // // }
    // 7-5删除逻辑优化. 优化7-4：不用find。应该先展示的消息提示组件，先删除
    // shift() 方法用于把数组的第一个元素从其中删除，并返回第一个元素的值。
    const currentMessage = queue.shift()!
    currentMessage.root.unmount()
    document.body.removeChild(currentMessage.messageContainer)
  }, 2000)
}

// 2、3-q1:由于window对象上没有onShow方法，所以ts报 类型“Window & typeof globalThis”上不存在属性“onShow”。ts(2339)
// a:需要ts声明扩充【知识扩展】
declare global {
  interface Window {
    onShow: () => void
  }
}

export default Message
